home *** CD-ROM | disk | FTP | other *** search
/ Freelog 125 / Freelog_MarsAvril2015_No125.iso / Musique / Quod Libet / quodlibet-3.3.0-installer.exe / bin / cgi.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2014-12-31  |  31KB  |  1,034 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.7)
  3.  
  4. '''Support module for CGI (Common Gateway Interface) scripts.
  5.  
  6. This module defines a number of utilities for use by CGI scripts
  7. written in Python.
  8. '''
  9. __version__ = '2.6'
  10. from operator import attrgetter
  11. import sys
  12. import os
  13. import UserDict
  14. import urlparse
  15. from warnings import filterwarnings, catch_warnings, warn
  16. with catch_warnings():
  17.     if sys.py3kwarning:
  18.         filterwarnings('ignore', '.*mimetools has been removed', DeprecationWarning)
  19.         filterwarnings('ignore', '.*rfc822 has been removed', DeprecationWarning)
  20.     import mimetools
  21.     import rfc822
  22.  
  23. try:
  24.     from cStringIO import StringIO
  25. except ImportError:
  26.     from StringIO import StringIO
  27.  
  28. __all__ = [
  29.     'MiniFieldStorage',
  30.     'FieldStorage',
  31.     'FormContentDict',
  32.     'SvFormContentDict',
  33.     'InterpFormContentDict',
  34.     'FormContent',
  35.     'parse',
  36.     'parse_qs',
  37.     'parse_qsl',
  38.     'parse_multipart',
  39.     'parse_header',
  40.     'print_exception',
  41.     'print_environ',
  42.     'print_form',
  43.     'print_directory',
  44.     'print_arguments',
  45.     'print_environ_usage',
  46.     'escape']
  47. logfile = ''
  48. logfp = None
  49.  
  50. def initlog(*allargs):
  51.     '''Write a log message, if there is a log file.
  52.  
  53.     Even though this function is called initlog(), you should always
  54.     use log(); log is a variable that is set either to initlog
  55.     (initially), to dolog (once the log file has been opened), or to
  56.     nolog (when logging is disabled).
  57.  
  58.     The first argument is a format string; the remaining arguments (if
  59.     any) are arguments to the % operator, so e.g.
  60.         log("%s: %s", "a", "b")
  61.     will write "a: b" to the log file, followed by a newline.
  62.  
  63.     If the global logfp is not None, it should be a file object to
  64.     which log data is written.
  65.  
  66.     If the global logfp is None, the global logfile may be a string
  67.     giving a filename to open, in append mode.  This file should be
  68.     world writable!!!  If the file can\'t be opened, logging is
  69.     silently disabled (since there is no safe place where we could
  70.     send an error message).
  71.  
  72.     '''
  73.     global logfp, log
  74.     if logfile and not logfp:
  75.         
  76.         try:
  77.             logfp = open(logfile, 'a')
  78.         except IOError:
  79.             pass
  80.         
  81.  
  82.     if not logfp:
  83.         log = nolog
  84.     else:
  85.         log = dolog
  86.     log(*allargs)
  87.  
  88.  
  89. def dolog(fmt, *args):
  90.     '''Write a log message to the log file.  See initlog() for docs.'''
  91.     logfp.write(fmt % args + '\n')
  92.  
  93.  
  94. def nolog(*allargs):
  95.     '''Dummy function, assigned to log when logging is disabled.'''
  96.     pass
  97.  
  98. log = initlog
  99. maxlen = 0
  100.  
  101. def parse(fp = None, environ = os.environ, keep_blank_values = 0, strict_parsing = 0):
  102.     '''Parse a query in the environment or from a file (default stdin)
  103.  
  104.         Arguments, all optional:
  105.  
  106.         fp              : file pointer; default: sys.stdin
  107.  
  108.         environ         : environment dictionary; default: os.environ
  109.  
  110.         keep_blank_values: flag indicating whether blank values in
  111.             percent-encoded forms should be treated as blank strings.
  112.             A true value indicates that blanks should be retained as
  113.             blank strings.  The default false value indicates that
  114.             blank values are to be ignored and treated as if they were
  115.             not included.
  116.  
  117.         strict_parsing: flag indicating what to do with parsing errors.
  118.             If false (the default), errors are silently ignored.
  119.             If true, errors raise a ValueError exception.
  120.     '''
  121.     if fp is None:
  122.         fp = sys.stdin
  123.     if 'REQUEST_METHOD' not in environ:
  124.         environ['REQUEST_METHOD'] = 'GET'
  125.     if environ['REQUEST_METHOD'] == 'POST':
  126.         (ctype, pdict) = parse_header(environ['CONTENT_TYPE'])
  127.         if ctype == 'multipart/form-data':
  128.             return parse_multipart(fp, pdict)
  129.         if None == 'application/x-www-form-urlencoded':
  130.             clength = int(environ['CONTENT_LENGTH'])
  131.             if maxlen and clength > maxlen:
  132.                 raise ValueError, 'Maximum content length exceeded'
  133.             qs = fp.read(clength)
  134.         else:
  135.             qs = ''
  136.         if 'QUERY_STRING' in environ:
  137.             if qs:
  138.                 qs = qs + '&'
  139.             qs = qs + environ['QUERY_STRING']
  140.         elif sys.argv[1:]:
  141.             if qs:
  142.                 qs = qs + '&'
  143.             qs = qs + sys.argv[1]
  144.         environ['QUERY_STRING'] = qs
  145.     elif 'QUERY_STRING' in environ:
  146.         qs = environ['QUERY_STRING']
  147.     elif sys.argv[1:]:
  148.         qs = sys.argv[1]
  149.     else:
  150.         qs = ''
  151.     environ['QUERY_STRING'] = qs
  152.     return urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
  153.  
  154.  
  155. def parse_qs(qs, keep_blank_values = 0, strict_parsing = 0):
  156.     '''Parse a query given as a string argument.'''
  157.     warn('cgi.parse_qs is deprecated, use urlparse.parse_qs instead', PendingDeprecationWarning, 2)
  158.     return urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
  159.  
  160.  
  161. def parse_qsl(qs, keep_blank_values = 0, strict_parsing = 0):
  162.     '''Parse a query given as a string argument.'''
  163.     warn('cgi.parse_qsl is deprecated, use urlparse.parse_qsl instead', PendingDeprecationWarning, 2)
  164.     return urlparse.parse_qsl(qs, keep_blank_values, strict_parsing)
  165.  
  166.  
  167. def parse_multipart(fp, pdict):
  168.     '''Parse multipart input.
  169.  
  170.     Arguments:
  171.     fp   : input file
  172.     pdict: dictionary containing other parameters of content-type header
  173.  
  174.     Returns a dictionary just like parse_qs(): keys are the field names, each
  175.     value is a list of values for that field.  This is easy to use but not
  176.     much good if you are expecting megabytes to be uploaded -- in that case,
  177.     use the FieldStorage class instead which is much more flexible.  Note
  178.     that content-type is the raw, unparsed contents of the content-type
  179.     header.
  180.  
  181.     XXX This does not parse nested multipart parts -- use FieldStorage for
  182.     that.
  183.  
  184.     XXX This should really be subsumed by FieldStorage altogether -- no
  185.     point in having two implementations of the same parsing algorithm.
  186.     Also, FieldStorage protects itself better against certain DoS attacks
  187.     by limiting the size of the data read in one chunk.  The API here
  188.     does not support that kind of protection.  This also affects parse()
  189.     since it can call parse_multipart().
  190.  
  191.     '''
  192.     boundary = ''
  193.     if 'boundary' in pdict:
  194.         boundary = pdict['boundary']
  195.     if not valid_boundary(boundary):
  196.         raise ValueError, 'Invalid boundary in multipart form: %r' % (boundary,)
  197.     nextpart = '--' + boundary
  198.     lastpart = '--' + boundary + '--'
  199.     partdict = { }
  200.     terminator = ''
  201.     while terminator != lastpart:
  202.         bytes = -1
  203.         data = None
  204.         if terminator:
  205.             headers = mimetools.Message(fp)
  206.             clength = headers.getheader('content-length')
  207.             if clength:
  208.                 
  209.                 try:
  210.                     bytes = int(clength)
  211.                 except ValueError:
  212.                     pass
  213.                 
  214.  
  215.             if bytes > 0:
  216.                 if maxlen and bytes > maxlen:
  217.                     raise ValueError, 'Maximum content length exceeded'
  218.                 data = fp.read(bytes)
  219.             else:
  220.                 data = ''
  221.         lines = []
  222.         while None:
  223.             line = fp.readline()
  224.             if not line:
  225.                 terminator = lastpart
  226.                 break
  227.             if line[:2] == '--':
  228.                 terminator = line.strip()
  229.                 if terminator in (nextpart, lastpart):
  230.                     break
  231.                 
  232.             continue
  233.             if data is None:
  234.                 continue
  235.             if bytes < 0 and lines:
  236.                 line = lines[-1]
  237.                 if line[-2:] == '\r\n':
  238.                     line = line[:-2]
  239.                 elif line[-1:] == '\n':
  240.                     line = line[:-1]
  241.                 lines[-1] = line
  242.                 data = ''.join(lines)
  243.             
  244.         line = headers['content-disposition']
  245.         if not line:
  246.             continue
  247.         (key, params) = parse_header(line)
  248.         if key != 'form-data':
  249.             continue
  250.         if 'name' in params:
  251.             name = params['name']
  252.         
  253.         if name in partdict:
  254.             partdict[name].append(data)
  255.             continue
  256.         partdict[name] = [
  257.             data]
  258.     return partdict
  259.  
  260.  
  261. def _parseparam(s):
  262.     while s[:1] == ';':
  263.         s = s[1:]
  264.         end = s.find(';')
  265.         while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
  266.             end = s.find(';', end + 1)
  267.         if end < 0:
  268.             end = len(s)
  269.         f = s[:end]
  270.         yield f.strip()
  271.         s = s[end:]
  272.  
  273.  
  274. def parse_header(line):
  275.     '''Parse a Content-type like header.
  276.  
  277.     Return the main content-type and a dictionary of options.
  278.  
  279.     '''
  280.     parts = _parseparam(';' + line)
  281.     key = parts.next()
  282.     pdict = { }
  283.     for p in parts:
  284.         i = p.find('=')
  285.         if i >= 0:
  286.             name = p[:i].strip().lower()
  287.             value = p[i + 1:].strip()
  288.             if len(value) >= 2:
  289.                 if value[-1] == value[-1]:
  290.                     pass
  291.                 elif value[-1] == '"':
  292.                     value = value[1:-1]
  293.                     value = value.replace('\\\\', '\\').replace('\\"', '"')
  294.         pdict[name] = value
  295.         continue
  296.     
  297.     return (key, pdict)
  298.  
  299.  
  300. class MiniFieldStorage:
  301.     '''Like FieldStorage, for use when no file uploads are possible.'''
  302.     filename = None
  303.     list = None
  304.     type = None
  305.     file = None
  306.     type_options = { }
  307.     disposition = None
  308.     disposition_options = { }
  309.     headers = { }
  310.     
  311.     def __init__(self, name, value):
  312.         '''Constructor from field name and value.'''
  313.         self.name = name
  314.         self.value = value
  315.  
  316.     
  317.     def __repr__(self):
  318.         '''Return printable representation.'''
  319.         return 'MiniFieldStorage(%r, %r)' % (self.name, self.value)
  320.  
  321.  
  322.  
  323. class FieldStorage:
  324.     """Store a sequence of fields, reading multipart/form-data.
  325.  
  326.     This class provides naming, typing, files stored on disk, and
  327.     more.  At the top level, it is accessible like a dictionary, whose
  328.     keys are the field names.  (Note: None can occur as a field name.)
  329.     The items are either a Python list (if there's multiple values) or
  330.     another FieldStorage or MiniFieldStorage object.  If it's a single
  331.     object, it has the following attributes:
  332.  
  333.     name: the field name, if specified; otherwise None
  334.  
  335.     filename: the filename, if specified; otherwise None; this is the
  336.         client side filename, *not* the file name on which it is
  337.         stored (that's a temporary file you don't deal with)
  338.  
  339.     value: the value as a *string*; for file uploads, this
  340.         transparently reads the file every time you request the value
  341.  
  342.     file: the file(-like) object from which you can read the data;
  343.         None if the data is stored a simple string
  344.  
  345.     type: the content-type, or None if not specified
  346.  
  347.     type_options: dictionary of options specified on the content-type
  348.         line
  349.  
  350.     disposition: content-disposition, or None if not specified
  351.  
  352.     disposition_options: dictionary of corresponding options
  353.  
  354.     headers: a dictionary(-like) object (sometimes rfc822.Message or a
  355.         subclass thereof) containing *all* headers
  356.  
  357.     The class is subclassable, mostly for the purpose of overriding
  358.     the make_file() method, which is called internally to come up with
  359.     a file open for reading and writing.  This makes it possible to
  360.     override the default choice of storing all files in a temporary
  361.     directory and unlinking them as soon as they have been opened.
  362.  
  363.     """
  364.     
  365.     def __init__(self, fp = None, headers = None, outerboundary = '', environ = os.environ, keep_blank_values = 0, strict_parsing = 0):
  366.         '''Constructor.  Read multipart/* until last part.
  367.  
  368.         Arguments, all optional:
  369.  
  370.         fp              : file pointer; default: sys.stdin
  371.             (not used when the request method is GET)
  372.  
  373.         headers         : header dictionary-like object; default:
  374.             taken from environ as per CGI spec
  375.  
  376.         outerboundary   : terminating multipart boundary
  377.             (for internal use only)
  378.  
  379.         environ         : environment dictionary; default: os.environ
  380.  
  381.         keep_blank_values: flag indicating whether blank values in
  382.             percent-encoded forms should be treated as blank strings.
  383.             A true value indicates that blanks should be retained as
  384.             blank strings.  The default false value indicates that
  385.             blank values are to be ignored and treated as if they were
  386.             not included.
  387.  
  388.         strict_parsing: flag indicating what to do with parsing errors.
  389.             If false (the default), errors are silently ignored.
  390.             If true, errors raise a ValueError exception.
  391.  
  392.         '''
  393.         method = 'GET'
  394.         self.keep_blank_values = keep_blank_values
  395.         self.strict_parsing = strict_parsing
  396.         if 'REQUEST_METHOD' in environ:
  397.             method = environ['REQUEST_METHOD'].upper()
  398.         self.qs_on_post = None
  399.         if method == 'GET' or method == 'HEAD':
  400.             if 'QUERY_STRING' in environ:
  401.                 qs = environ['QUERY_STRING']
  402.             elif sys.argv[1:]:
  403.                 qs = sys.argv[1]
  404.             else:
  405.                 qs = ''
  406.             fp = StringIO(qs)
  407.             if headers is None:
  408.                 headers = {
  409.                     'content-type': 'application/x-www-form-urlencoded' }
  410.             
  411.         self.fp = None if headers is None else sys.stdin
  412.         self.headers = headers
  413.         self.outerboundary = outerboundary
  414.         cdisp = ''
  415.         pdict = { }
  416.         if 'content-disposition' in self.headers:
  417.             (cdisp, pdict) = parse_header(self.headers['content-disposition'])
  418.         self.disposition = cdisp
  419.         self.disposition_options = pdict
  420.         self.name = None
  421.         if 'name' in pdict:
  422.             self.name = pdict['name']
  423.         self.filename = None
  424.         if 'filename' in pdict:
  425.             self.filename = pdict['filename']
  426.         if 'content-type' in self.headers:
  427.             (ctype, pdict) = parse_header(self.headers['content-type'])
  428.         elif self.outerboundary or method != 'POST':
  429.             ctype = 'text/plain'
  430.             pdict = { }
  431.         else:
  432.             ctype = 'application/x-www-form-urlencoded'
  433.             pdict = { }
  434.         self.type = ctype
  435.         self.type_options = pdict
  436.         self.innerboundary = ''
  437.         if 'boundary' in pdict:
  438.             self.innerboundary = pdict['boundary']
  439.         clen = -1
  440.         if 'content-length' in self.headers:
  441.             
  442.             try:
  443.                 clen = int(self.headers['content-length'])
  444.             except ValueError:
  445.                 pass
  446.  
  447.             if maxlen and clen > maxlen:
  448.                 raise ValueError, 'Maximum content length exceeded'
  449.         self.length = clen
  450.         self.list = None
  451.         self.file = None
  452.         self.done = 0
  453.         if ctype == 'application/x-www-form-urlencoded':
  454.             self.read_urlencoded()
  455.         elif ctype[:10] == 'multipart/':
  456.             self.read_multi(environ, keep_blank_values, strict_parsing)
  457.         else:
  458.             self.read_single()
  459.  
  460.     
  461.     def __repr__(self):
  462.         '''Return a printable representation.'''
  463.         return 'FieldStorage(%r, %r, %r)' % (self.name, self.filename, self.value)
  464.  
  465.     
  466.     def __iter__(self):
  467.         return iter(self.keys())
  468.  
  469.     
  470.     def __getattr__(self, name):
  471.         if name != 'value':
  472.             raise AttributeError, name
  473.         if self.file:
  474.             self.file.seek(0)
  475.             value = self.file.read()
  476.             self.file.seek(0)
  477.         elif self.list is not None:
  478.             value = self.list
  479.         else:
  480.             value = None
  481.         return value
  482.  
  483.     
  484.     def __getitem__(self, key):
  485.         '''Dictionary style indexing.'''
  486.         if self.list is None:
  487.             raise TypeError, 'not indexable'
  488.         found = []
  489.         for item in self.list:
  490.             if item.name == key:
  491.                 found.append(item)
  492.                 continue
  493.         if not found:
  494.             raise KeyError, key
  495.         if len(found) == 1:
  496.             return found[0]
  497.         return None
  498.  
  499.     
  500.     def getvalue(self, key, default = None):
  501.         """Dictionary style get() method, including 'value' lookup."""
  502.         if key in self:
  503.             value = self[key]
  504.             if type(value) is type([]):
  505.                 return map(attrgetter('value'), value)
  506.             return None.value
  507.         return default
  508.  
  509.     
  510.     def getfirst(self, key, default = None):
  511.         ''' Return the first value received.'''
  512.         if key in self:
  513.             value = self[key]
  514.             if type(value) is type([]):
  515.                 return value[0].value
  516.             return None.value
  517.         return default
  518.  
  519.     
  520.     def getlist(self, key):
  521.         ''' Return list of received values.'''
  522.         if key in self:
  523.             value = self[key]
  524.             if type(value) is type([]):
  525.                 return map(attrgetter('value'), value)
  526.             return [
  527.                 None.value]
  528.         return []
  529.  
  530.     
  531.     def keys(self):
  532.         '''Dictionary style keys() method.'''
  533.         if self.list is None:
  534.             raise TypeError, 'not indexable'
  535.         return list(set((lambda .0: pass)(self.list)))
  536.  
  537.     
  538.     def has_key(self, key):
  539.         '''Dictionary style has_key() method.'''
  540.         if self.list is None:
  541.             raise TypeError, 'not indexable'
  542.         return (any,)((lambda .0: pass)(self.list))
  543.  
  544.     
  545.     def __contains__(self, key):
  546.         '''Dictionary style __contains__ method.'''
  547.         if self.list is None:
  548.             raise TypeError, 'not indexable'
  549.         return (any,)((lambda .0: pass)(self.list))
  550.  
  551.     
  552.     def __len__(self):
  553.         '''Dictionary style len(x) support.'''
  554.         return len(self.keys())
  555.  
  556.     
  557.     def __nonzero__(self):
  558.         return bool(self.list)
  559.  
  560.     
  561.     def read_urlencoded(self):
  562.         '''Internal: read data in query string format.'''
  563.         qs = self.fp.read(self.length)
  564.         if self.qs_on_post:
  565.             qs += '&' + self.qs_on_post
  566.         self.list = list = []
  567.         for key, value in urlparse.parse_qsl(qs, self.keep_blank_values, self.strict_parsing):
  568.             list.append(MiniFieldStorage(key, value))
  569.         
  570.         self.skip_lines()
  571.  
  572.     FieldStorageClass = None
  573.     
  574.     def read_multi(self, environ, keep_blank_values, strict_parsing):
  575.         '''Internal: read a part that is itself multipart.'''
  576.         ib = self.innerboundary
  577.         if not valid_boundary(ib):
  578.             raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,)
  579.         self.list = []
  580.         klass = None if self.qs_on_post else self.__class__
  581.         part = klass(self.fp, { }, ib, environ, keep_blank_values, strict_parsing)
  582.         while not part.done:
  583.             headers = rfc822.Message(self.fp)
  584.             part = klass(self.fp, headers, ib, environ, keep_blank_values, strict_parsing)
  585.             self.list.append(part)
  586.         self.skip_lines()
  587.  
  588.     
  589.     def read_single(self):
  590.         '''Internal: read an atomic part.'''
  591.         if self.length >= 0:
  592.             self.read_binary()
  593.             self.skip_lines()
  594.         else:
  595.             self.read_lines()
  596.         self.file.seek(0)
  597.  
  598.     bufsize = 8192
  599.     
  600.     def read_binary(self):
  601.         '''Internal: read binary data.'''
  602.         self.file = self.make_file('b')
  603.         todo = self.length
  604.         if todo >= 0:
  605.             while todo > 0:
  606.                 data = self.fp.read(min(todo, self.bufsize))
  607.                 if not data:
  608.                     self.done = -1
  609.                     break
  610.                 self.file.write(data)
  611.                 todo = todo - len(data)
  612.  
  613.     
  614.     def read_lines(self):
  615.         '''Internal: read lines until EOF or outerboundary.'''
  616.         self.file = self._FieldStorage__file = StringIO()
  617.         if self.outerboundary:
  618.             self.read_lines_to_outerboundary()
  619.         else:
  620.             self.read_lines_to_eof()
  621.  
  622.     
  623.     def __write(self, line):
  624.         if self._FieldStorage__file is not None and self._FieldStorage__file.tell() + len(line) > 1000:
  625.             self.file = self.make_file('')
  626.             self.file.write(self._FieldStorage__file.getvalue())
  627.             self._FieldStorage__file = None
  628.         
  629.         self.file.write(line)
  630.  
  631.     
  632.     def read_lines_to_eof(self):
  633.         '''Internal: read lines until EOF.'''
  634.         while None:
  635.             line = self.fp.readline(65536)
  636.             if not line:
  637.                 self.done = -1
  638.                 break
  639.             continue
  640.             return None
  641.  
  642.     
  643.     def read_lines_to_outerboundary(self):
  644.         '''Internal: read lines until outerboundary.'''
  645.         next = '--' + self.outerboundary
  646.         last = next + '--'
  647.         delim = ''
  648.         last_line_lfend = True
  649.         while None:
  650.             line = self.fp.readline(65536)
  651.             if not line:
  652.                 self.done = -1
  653.                 break
  654.             if delim == '\r':
  655.                 line = delim + line
  656.                 delim = ''
  657.             if line[:2] == '--' and last_line_lfend:
  658.                 strippedline = line.strip()
  659.                 if strippedline == next:
  660.                     break
  661.                 if strippedline == last:
  662.                     self.done = 1
  663.                     break
  664.                 
  665.             odelim = delim
  666.             if line[-2:] == '\r\n':
  667.                 delim = '\r\n'
  668.                 line = line[:-2]
  669.                 last_line_lfend = True
  670.             elif line[-1] == '\n':
  671.                 delim = '\n'
  672.                 line = line[:-1]
  673.                 last_line_lfend = True
  674.             elif line[-1] == '\r':
  675.                 delim = '\r'
  676.                 line = line[:-1]
  677.                 last_line_lfend = False
  678.             else:
  679.                 delim = ''
  680.                 last_line_lfend = False
  681.             continue
  682.             return None
  683.  
  684.     
  685.     def skip_lines(self):
  686.         '''Internal: skip lines until outer boundary if defined.'''
  687.         if not (self.outerboundary) or self.done:
  688.             return None
  689.         next = None + self.outerboundary
  690.         last = next + '--'
  691.         last_line_lfend = True
  692.         while None:
  693.             line = self.fp.readline(65536)
  694.             if not line:
  695.                 self.done = -1
  696.                 break
  697.             if line[:2] == '--' and last_line_lfend:
  698.                 strippedline = line.strip()
  699.                 if strippedline == next:
  700.                     break
  701.                 if strippedline == last:
  702.                     self.done = 1
  703.                     break
  704.                 
  705.             last_line_lfend = line.endswith('\n')
  706.             continue
  707.             return None
  708.  
  709.     
  710.     def make_file(self, binary = None):
  711.         """Overridable: return a readable & writable file.
  712.  
  713.         The file will be used as follows:
  714.         - data is written to it
  715.         - seek(0)
  716.         - data is read from it
  717.  
  718.         The 'binary' argument is unused -- the file is always opened
  719.         in binary mode.
  720.  
  721.         This version opens a temporary file for reading and writing,
  722.         and immediately deletes (unlinks) it.  The trick (on Unix!) is
  723.         that the file can still be used, but it can't be opened by
  724.         another process, and it will automatically be deleted when it
  725.         is closed or when the current process terminates.
  726.  
  727.         If you want a more permanent file, you derive a class which
  728.         overrides this method.  If you want a visible temporary file
  729.         that is nevertheless automatically deleted when the script
  730.         terminates, try defining a __del__ method in a derived class
  731.         which unlinks the temporary files you have created.
  732.  
  733.         """
  734.         import tempfile as tempfile
  735.         return tempfile.TemporaryFile('w+b')
  736.  
  737.  
  738.  
  739. class FormContentDict(UserDict.UserDict):
  740.     '''Form content as dictionary with a list of values per field.
  741.  
  742.     form = FormContentDict()
  743.  
  744.     form[key] -> [value, value, ...]
  745.     key in form -> Boolean
  746.     form.keys() -> [key, key, ...]
  747.     form.values() -> [[val, val, ...], [val, val, ...], ...]
  748.     form.items() ->  [(key, [val, val, ...]), (key, [val, val, ...]), ...]
  749.     form.dict == {key: [val, val, ...], ...}
  750.  
  751.     '''
  752.     
  753.     def __init__(self, environ = os.environ, keep_blank_values = 0, strict_parsing = 0):
  754.         self.dict = self.data = parse(environ = environ, keep_blank_values = keep_blank_values, strict_parsing = strict_parsing)
  755.         self.query_string = environ['QUERY_STRING']
  756.  
  757.  
  758.  
  759. class SvFormContentDict(FormContentDict):
  760.     '''Form content as dictionary expecting a single value per field.
  761.  
  762.     If you only expect a single value for each field, then form[key]
  763.     will return that single value.  It will raise an IndexError if
  764.     that expectation is not true.  If you expect a field to have
  765.     possible multiple values, than you can use form.getlist(key) to
  766.     get all of the values.  values() and items() are a compromise:
  767.     they return single strings where there is a single value, and
  768.     lists of strings otherwise.
  769.  
  770.     '''
  771.     
  772.     def __getitem__(self, key):
  773.         if len(self.dict[key]) > 1:
  774.             raise IndexError, 'expecting a single value'
  775.         return self.dict[key][0]
  776.  
  777.     
  778.     def getlist(self, key):
  779.         return self.dict[key]
  780.  
  781.     
  782.     def values(self):
  783.         result = []
  784.         for value in self.dict.values():
  785.             if len(value) == 1:
  786.                 result.append(value[0])
  787.                 continue
  788.             result.append(value)
  789.         
  790.         return result
  791.  
  792.     
  793.     def items(self):
  794.         result = []
  795.         for key, value in self.dict.items():
  796.             if len(value) == 1:
  797.                 result.append((key, value[0]))
  798.                 continue
  799.             result.append((key, value))
  800.         
  801.         return result
  802.  
  803.  
  804.  
  805. class InterpFormContentDict(SvFormContentDict):
  806.     '''This class is present for backwards compatibility only.'''
  807.     
  808.     def __getitem__(self, key):
  809.         v = SvFormContentDict.__getitem__(self, key)
  810.         if v[0] in '0123456789+-.':
  811.             
  812.             try:
  813.                 return int(v)
  814.             except ValueError:
  815.                 
  816.                 try:
  817.                     return float(v)
  818.                 except ValueError:
  819.                     pass
  820.                 
  821.  
  822.             
  823.  
  824.         return v.strip()
  825.  
  826.     
  827.     def values(self):
  828.         result = []
  829.         for key in self.keys():
  830.             
  831.             try:
  832.                 result.append(self[key])
  833.             continue
  834.             except IndexError:
  835.                 result.append(self.dict[key])
  836.                 continue
  837.             
  838.  
  839.         
  840.         return result
  841.  
  842.     
  843.     def items(self):
  844.         result = []
  845.         for key in self.keys():
  846.             
  847.             try:
  848.                 result.append((key, self[key]))
  849.             continue
  850.             except IndexError:
  851.                 result.append((key, self.dict[key]))
  852.                 continue
  853.             
  854.  
  855.         
  856.         return result
  857.  
  858.  
  859.  
  860. class FormContent(FormContentDict):
  861.     '''This class is present for backwards compatibility only.'''
  862.     
  863.     def values(self, key):
  864.         if key in self.dict:
  865.             return self.dict[key]
  866.         return None
  867.  
  868.     
  869.     def indexed_value(self, key, location):
  870.         if key in self.dict:
  871.             if len(self.dict[key]) > location:
  872.                 return self.dict[key][location]
  873.             return None
  874.         return None
  875.  
  876.     
  877.     def value(self, key):
  878.         if key in self.dict:
  879.             return self.dict[key][0]
  880.         return None
  881.  
  882.     
  883.     def length(self, key):
  884.         return len(self.dict[key])
  885.  
  886.     
  887.     def stripped(self, key):
  888.         if key in self.dict:
  889.             return self.dict[key][0].strip()
  890.         return None
  891.  
  892.     
  893.     def pars(self):
  894.         return self.dict
  895.  
  896.  
  897.  
  898. def test(environ = os.environ):
  899.     '''Robust test CGI script, usable as main program.
  900.  
  901.     Write minimal HTTP headers and dump all information provided to
  902.     the script in HTML form.
  903.  
  904.     '''
  905.     global maxlen
  906.     print 'Content-type: text/html'
  907.     print 
  908.     sys.stderr = sys.stdout
  909.     
  910.     try:
  911.         form = FieldStorage()
  912.         print_directory()
  913.         print_arguments()
  914.         print_form(form)
  915.         print_environ(environ)
  916.         print_environ_usage()
  917.         
  918.         def f():
  919.             exec 'testing print_exception() -- <I>italics?</I>'
  920.  
  921.         
  922.         def g(f = f):
  923.             f()
  924.  
  925.         print '<H3>What follows is a test, not an actual exception:</H3>'
  926.         g()
  927.     except:
  928.         print_exception()
  929.  
  930.     print '<H1>Second try with a small maxlen...</H1>'
  931.     maxlen = 50
  932.     
  933.     try:
  934.         form = FieldStorage()
  935.         print_directory()
  936.         print_arguments()
  937.         print_form(form)
  938.         print_environ(environ)
  939.     except:
  940.         print_exception()
  941.  
  942.  
  943.  
  944. def print_exception(type = None, value = None, tb = None, limit = None):
  945.     if type is None:
  946.         (type, value, tb) = sys.exc_info()
  947.     import traceback as traceback
  948.     print 
  949.     print '<H3>Traceback (most recent call last):</H3>'
  950.     list = traceback.format_tb(tb, limit) + traceback.format_exception_only(type, value)
  951.     print '<PRE>%s<B>%s</B></PRE>' % (escape(''.join(list[:-1])), escape(list[-1]))
  952.     del tb
  953.  
  954.  
  955. def print_environ(environ = os.environ):
  956.     '''Dump the shell environment as HTML.'''
  957.     keys = environ.keys()
  958.     keys.sort()
  959.     print 
  960.     print '<H3>Shell Environment:</H3>'
  961.     print '<DL>'
  962.     for key in keys:
  963.         print '<DT>', escape(key), '<DD>', escape(environ[key])
  964.     
  965.     print '</DL>'
  966.     print 
  967.  
  968.  
  969. def print_form(form):
  970.     '''Dump the contents of a form as HTML.'''
  971.     keys = form.keys()
  972.     keys.sort()
  973.     print 
  974.     print '<H3>Form Contents:</H3>'
  975.     if not keys:
  976.         print '<P>No form fields.'
  977.     print '<DL>'
  978.     for key in keys:
  979.         print '<DT>' + escape(key) + ':',
  980.         value = form[key]
  981.         print '<i>' + escape(repr(type(value))) + '</i>'
  982.         print '<DD>' + escape(repr(value))
  983.     
  984.     print '</DL>'
  985.     print 
  986.  
  987.  
  988. def print_directory():
  989.     '''Dump the current directory as HTML.'''
  990.     print 
  991.     print '<H3>Current Working Directory:</H3>'
  992.     
  993.     try:
  994.         pwd = os.getcwd()
  995.     except os.error:
  996.         msg = None
  997.         print 'os.error:', escape(str(msg))
  998.  
  999.     print escape(pwd)
  1000.     print 
  1001.  
  1002.  
  1003. def print_arguments():
  1004.     print 
  1005.     print '<H3>Command Line Arguments:</H3>'
  1006.     print 
  1007.     print sys.argv
  1008.     print 
  1009.  
  1010.  
  1011. def print_environ_usage():
  1012.     '''Dump a list of environment variables used by CGI as HTML.'''
  1013.     print '\n<H3>These environment variables could have been set:</H3>\n<UL>\n<LI>AUTH_TYPE\n<LI>CONTENT_LENGTH\n<LI>CONTENT_TYPE\n<LI>DATE_GMT\n<LI>DATE_LOCAL\n<LI>DOCUMENT_NAME\n<LI>DOCUMENT_ROOT\n<LI>DOCUMENT_URI\n<LI>GATEWAY_INTERFACE\n<LI>LAST_MODIFIED\n<LI>PATH\n<LI>PATH_INFO\n<LI>PATH_TRANSLATED\n<LI>QUERY_STRING\n<LI>REMOTE_ADDR\n<LI>REMOTE_HOST\n<LI>REMOTE_IDENT\n<LI>REMOTE_USER\n<LI>REQUEST_METHOD\n<LI>SCRIPT_NAME\n<LI>SERVER_NAME\n<LI>SERVER_PORT\n<LI>SERVER_PROTOCOL\n<LI>SERVER_ROOT\n<LI>SERVER_SOFTWARE\n</UL>\nIn addition, HTTP headers sent by the server may be passed in the\nenvironment as well.  Here are some common variable names:\n<UL>\n<LI>HTTP_ACCEPT\n<LI>HTTP_CONNECTION\n<LI>HTTP_HOST\n<LI>HTTP_PRAGMA\n<LI>HTTP_REFERER\n<LI>HTTP_USER_AGENT\n</UL>\n'
  1014.  
  1015.  
  1016. def escape(s, quote = None):
  1017.     '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
  1018.     If the optional flag quote is true, the quotation mark character (")
  1019.     is also translated.'''
  1020.     s = s.replace('&', '&')
  1021.     s = s.replace('<', '<')
  1022.     s = s.replace('>', '>')
  1023.     if quote:
  1024.         s = s.replace('"', '"')
  1025.     return s
  1026.  
  1027.  
  1028. def valid_boundary(s, _vb_pattern = '^[ -~]{0,200}[!-~]$'):
  1029.     import re as re
  1030.     return re.match(_vb_pattern, s)
  1031.  
  1032. if __name__ == '__main__':
  1033.     test()
  1034.